#pragma once
#include"Inet_data.h"

class Udp : public nocopy
{
public:
    Udp(const string &ip, const uint16_t &port)
        : _ip(ip), _port(port)
    {
    }

    void Creat_socket()
    {
        // 1.创建套接字(创建文件细节)
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建套接字(域、套接字类型、协议)参数2基本可以固定tcp/udp
        if (_sockfd < 0)
        {
            cerr << "创建套接字失败" << endl;
            exit(-1);
        }
    }

    void Bind()
    {
        // 2.绑定(网络信息与文件信息相关联)
        struct sockaddr_in local;      //
        local.sin_family = AF_INET;    // 域，用于sockaddr类型接收时的辨别字段
        local.sin_port = htons(_port); // 端口号 主机转网络(用于发送)
        // local.sin_addr.s_addr = inet_addr(_ip.c_str()); // 四字节ip+转换成网络序列
        local.sin_addr.s_addr = INADDR_ANY; // 地址任意

        int n = bind(_sockfd, (sockaddr *)&local, sizeof(local));
        if (n != 0)
        {
            cerr << "套接字绑定失败" << endl;
        }
    }

    void Save(sockaddr_in client)
    {
        Inet_data tmp(_sockfd,client);
        for(auto cl:_Client_list)
        {
            if(tmp==cl)
                return;
        }
        _Client_list.push_back(tmp);
    }

    void Run_server()
    {
        char buffer[1024]={0}; // 接收数据

        while (1) // 服务器端一直运行不退出
        {
            struct sockaddr_in foreign; // 客户端的套接字信息(输入输出型参数)
            socklen_t len = sizeof(foreign);

            size_t n = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&foreign, &len);
            buffer[n] = 0; // 结尾

            // 获取客户端ip+port信息
            cout << "recive info: " << buffer<<' ';
            Inet_data cl(_sockfd,foreign);
            cl.Inet_info();

            //保存客户端信息
            Save(foreign);

            // 数据分发给所有的客户
            for(auto cl:_Client_list)
            {
                struct sockaddr_in tmp;
                tmp.sin_family = AF_INET;                     // 域，用于sockaddr类型接收时的辨别字段
                tmp.sin_port = cl.get_port();                  // 端口号 主机转网络(用于发送)
                tmp.sin_addr.s_addr = cl.get_ip(); // 四字节ip+转换成网络序列
                sendto(_sockfd, buffer, strlen(buffer), 0, (sockaddr *)&tmp, sizeof(tmp));
            }
            
        }
    }


    ~Udp()
    {
        close(_sockfd);
    }

private:
    string _ip;
    uint16_t _port;
    int _sockfd; // 套接字文件描述符
    vector<Inet_data> _Client_list;

};